package api

import (
	"bytes"
	"database/sql"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"io"
	"log"
	"mime/multipart"
	"net/http"
	"os"
	"path"
	"path/filepath"
	"strconv"
	"strings"
	"time"
	"tuiwen-go/internal/config"
	"tuiwen-go/internal/db"
)

// JSONResponse 通用的data JSON 响应结构
type JSONResponse struct {
	Code int         `json:"code"`
	Msg  string      `json:"msg"`
	Data interface{} `json:"data,omitempty"`
}

// websocket 响应结构
type WxJSONResponse struct {
	Type string      `json:"type"`
	Code int         `json:"code"`
	Msg  string      `json:"msg"`
	Data interface{} `json:"data,omitempty"`
}

// writeJSONResponse 写入 JSON 响应
func writeJSONResponse(w http.ResponseWriter, code int, msg string, data interface{}) {
	w.Header().Set("Content-Type", "application/json")

	if code == 0 {
		// Success: return data directly
		w.WriteHeader(http.StatusOK)
		response := JSONResponse{
			Code: code,
			Msg:  msg,
			Data: data,
		}
		if err := json.NewEncoder(w).Encode(response); err != nil {
			log.Printf("Error encoding JSON response: %v", err)
		}
	} else {
		// Failure: return error object
		w.WriteHeader(http.StatusOK) // 总是返回 200 OK，错误信息放在 JSON body 中
		response := JSONResponse{
			Code: code,
			Msg:  msg,
			Data: data,
		}
		if err := json.NewEncoder(w).Encode(response); err != nil {
			log.Printf("Error encoding JSON response: %v", err)
		}
	}
}
func writeResponse(w http.ResponseWriter, code int, msg string, data interface{}) {
	w.Header().Set("Content-Type", "application/json")

	if code == 0 {
		// Success: return data directly
		w.WriteHeader(http.StatusOK)
		if err := json.NewEncoder(w).Encode(data); err != nil {
			log.Printf("Error encoding JSON response: %v", err)
		}
	} else {
		// Failure: return error object
		w.WriteHeader(http.StatusOK) // 总是返回 200 OK，错误信息放在 JSON body 中
		response := JSONResponse{
			Code: code,
			Msg:  msg,
			Data: data,
		}
		if err := json.NewEncoder(w).Encode(response); err != nil {
			log.Printf("Error encoding JSON response: %v", err)
		}
	}
}

// QueryProjects 处理 GET /projects/query 请求
func QueryProjects(w http.ResponseWriter, r *http.Request) {
	name := r.URL.Query().Get("name")
	var rows *sql.Rows
	var err error

	if name != "" {
		sqlQuery := "SELECT id, name, textContent, createTime, status, draft FROM project WHERE name LIKE ? ORDER BY id DESC"
		rows, err = db.Query(sqlQuery, "%"+name+"%")
	} else {
		sqlQuery := "SELECT id, name, textContent, createTime, status, draft FROM project ORDER BY id DESC"
		rows, err = db.Query(sqlQuery)
	}

	if err != nil {
		log.Printf("Error querying projects: %v", err)
		writeJSONResponse(w, 1, "查询项目失败", nil)
		return
	}
	defer rows.Close()

	var projects []map[string]interface{}
	for rows.Next() {
		var id int
		var projectName, textContent, draft sql.NullString // Use NullString for nullable columns
		var createTime time.Time
		var status int

		err := rows.Scan(&id, &projectName, &textContent, &createTime, &status, &draft)
		if err != nil {
			log.Printf("Error scanning project row: %v", err)
			continue // Skip this row, or handle error appropriately
		}

		project := map[string]interface{}{
			"id":          id,
			"name":        projectName.String,
			"textContent": textContent.String,
			"createTime":  createTime,
			"status":      status,
			"draft":       nil, // Default to nil
		}
		if draft.Valid {
			// Assuming the draft path needs to be prefixed for the frontend
			project["draft"] = "/" + strings.ReplaceAll(strings.ReplaceAll(draft.String, "..\\public", "public"), "../public", "public")
		}

		projects = append(projects, project)
	}

	if err = rows.Err(); err != nil {
		log.Printf("Error iterating project rows: %v", err)
		writeJSONResponse(w, 1, "查询项目失败", nil)
		return
	}

	writeResponse(w, 0, "查询成功", projects)
}

// GetSettings 处理 GET /settings 请求
func GetSettings(w http.ResponseWriter, r *http.Request) {
	settings := config.GetAllSettings()
	writeJSONResponse(w, 0, "获取配置成功", settings)
}

// UpdateSetting 处理 POST /setting/update 请求
func UpdateSetting(w http.ResponseWriter, r *http.Request) {
	var body struct {
		Key   string `json:"key"`
		Value string `json:"value"`
	}

	if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
		writeJSONResponse(w, 1, "请求参数错误", nil)
		return
	}

	if body.Key == "" {
		writeJSONResponse(w, 1, "Key 不能为空", nil)
		return
	}

	if err := config.UpdateSetting(body.Key, body.Value); err != nil {
		writeJSONResponse(w, 1, fmt.Sprintf("更新配置失败: %v", err), nil)
		return
	}

	writeJSONResponse(w, 0, "更新配置成功", nil)
}

// DeleteProject 处理 POST /project/delete 请求
func DeleteProject(w http.ResponseWriter, r *http.Request) {
	var body struct {
		ProjectID int `json:"project_id"`
	}
	if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
		writeJSONResponse(w, 1, "请求参数错误", nil)
		return
	}

	if body.ProjectID == 0 {
		writeJSONResponse(w, 1, "项目ID不能为空", nil)
		return
	}

	// Start a transaction to delete from project and text tables
	tx, err := db.DB.Begin()
	if err != nil {
		log.Printf("Error starting transaction: %v", err)
		writeJSONResponse(w, 1, "删除失败", nil)
		return
	}

	// Delete from text table first (due to foreign key constraints if any)
	_, err = tx.Exec("DELETE FROM text WHERE project_id = ?", body.ProjectID)
	if err != nil {
		tx.Rollback()
		log.Printf("Error deleting from text table: %v", err)
		writeJSONResponse(w, 1, "删除失败", nil)
		return
	}

	// Delete from project table
	result, err := tx.Exec("DELETE FROM project WHERE id = ?", body.ProjectID)
	if err != nil {
		tx.Rollback()
		log.Printf("Error deleting from project table: %v", err)
		writeJSONResponse(w, 1, "删除失败", nil)
		return
	}

	rowsAffected, err := result.RowsAffected()
	if err != nil {
		tx.Rollback()
		log.Printf("Error getting rows affected: %v", err)
		writeJSONResponse(w, 1, "删除失败", nil)
		return
	}

	if rowsAffected == 0 {
		tx.Rollback()
		writeJSONResponse(w, 1, "项目不存在或已删除", nil)
		return
	}

	err = tx.Commit()
	if err != nil {
		log.Printf("Error committing transaction: %v", err)
		writeJSONResponse(w, 1, "删除失败", nil)
		return
	}

	writeJSONResponse(w, 0, "删除成功", nil)
}

// QueryProject 处理 GET /project/query 请求
func QueryProject(w http.ResponseWriter, r *http.Request) {
	projectIDStr := r.URL.Query().Get("project_id")
	if projectIDStr == "" {
		writeJSONResponse(w, 1, "项目ID不能为空", nil)
		return
	}
	projectID, err := strconv.Atoi(projectIDStr)
	if err != nil {
		writeJSONResponse(w, 1, "项目ID格式错误", nil)
		return
	}

	sqlQuery := "SELECT * from (\n" +
		"SELECT\n" +
		"	a.id,\n" +
		"	project_id,\n" +
		"	content,\n" +
		"	role_ids,\n" +
		"	GROUP_CONCAT(b. NAME) AS role_names,\n" +
		"	split,\n" +
		"	a.prompt,\n" +
		"	audio,\n" +
		"	audio_duration,\n" +
		"	image,\n" +
		"	image_comfyui\n" +
		"FROM\n" +
		"	text a\n" +
		"LEFT JOIN role b ON FIND_IN_SET(b.id, a.role_ids)\n" +
		"GROUP BY\n" +
		"	a.id) t\n" +
		"WHERE\n" +
		"	t.project_id = ?\n" +
		"ORDER BY\n" +
		"	t.id"
	rows, err := db.Query(sqlQuery, projectID)
	if err != nil {
		log.Printf("Error querying project details: %v", err)
		writeJSONResponse(w, 1, "查询项目详情失败", nil)
		return
	}
	defer rows.Close()

	var details []map[string]interface{}
	for rows.Next() {
		var id, projectID int
		var content, role_ids, role_names, split, prompt, audio, image, image_comfyui sql.NullString
		var audioDurationStr sql.NullString // Change scan target to string

		err := rows.Scan(&id, &projectID, &content, &role_ids, &role_names, &split, &prompt, &audio, &audioDurationStr, &image, &image_comfyui)
		if err != nil {
			log.Printf("Error scanning project detail row: %v", err)
			continue
		}

		var audioDuration sql.NullInt64 // Declare the target NullInt64
		if audioDurationStr.Valid && audioDurationStr.String != "" {
			dur, err := strconv.ParseInt(audioDurationStr.String, 10, 64)
			if err == nil {
				audioDuration = sql.NullInt64{Int64: dur, Valid: true}
			} else {
				log.Printf("Error converting audio_duration string '%s' to int64: %v", audioDurationStr.String, err)
				// Keep audioDuration as invalid/zero value
			}
		}

		detail := map[string]interface{}{
			"id":             id,
			"project_id":     projectID,
			"content":        content.String,
			"role_ids":       role_ids.String,
			"role_names":     role_names.String,
			"split":          nil, // Default to nil
			"prompt":         prompt.String,
			"audio":          nil,                 // Default to nil
			"audio_duration": audioDuration.Int64, // Use the converted value
			"image":          nil,                 // Default to nil
			"image_comfyui":  nil,
		}

		if split.Valid {
			detail["split"] = split.String
		}
		if audio.Valid {
			detail["audio"] = audio.String
		}
		if image.Valid {
			detail["image"] = image.String
		}
		if image_comfyui.Valid {
			detail["image_comfyui"] = image_comfyui.String
		}

		details = append(details, detail)
	}

	if err = rows.Err(); err != nil {
		log.Printf("Error iterating project detail rows: %v", err)
		writeJSONResponse(w, 1, "查询项目详情失败", nil)
		return
	}

	writeJSONResponse(w, 0, "查询成功", details)
}

// DeleteDetail handles POST /detail/delete request
func DeleteDetail(w http.ResponseWriter, r *http.Request) {
	log.Printf("Received request for /detail/delete")

	var body struct {
		Ids  []int  `json:"ids"`
		Type string `json:"type"`
	} // Assuming 'ids' is an array of integers and 'type' is a string

	if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
		writeJSONResponse(w, 1, "请求参数错误", nil)
		return
	}

	if len(body.Ids) == 0 || body.Type == "" {
		writeJSONResponse(w, 1, "ids或type不能为空", nil)
		return
	}

	// Validate the 'type' parameter to prevent SQL injection
	allowedTypes := map[string]bool{"split": true, "prompt": true, "audio": true, "image": true}
	if _, ok := allowedTypes[body.Type]; !ok {
		writeJSONResponse(w, 1, "无效的type参数", nil)
		return
	}

	// Construct the SQL query dynamically based on the validated type
	// Using IN clause with multiple IDs requires careful handling of parameters
	// A common way is to build the query string with placeholders and pass the IDs as args
	placeholders := strings.Repeat("?, ", len(body.Ids))
	placeholders = placeholders[:len(placeholders)-2] // Remove trailing ", "

	// Prepare the arguments slice
	args := make([]interface{}, len(body.Ids))
	for i, id := range body.Ids {
		args[i] = id
	}

	// If deleting images, rename the files first
	if body.Type == "image" {
		// Query for current image paths
		queryImagePaths := fmt.Sprintf("SELECT id, image FROM text WHERE id IN (%s) AND image IS NOT NULL", placeholders)
		rows, err := db.Query(queryImagePaths, args...)
		if err != nil {
			log.Printf("Error querying image paths: %v", err)
			// Continue with database update even if renaming fails
		}
		defer rows.Close()

		for rows.Next() {
			var id int
			var imagePath string
			if err := rows.Scan(&id, &imagePath); err != nil {
				log.Printf("Error scanning image path: %v", err)
				continue
			}

			if imagePath != "" {
				// Construct new filename with timestamp
				currentTime := time.Now().Unix()
				ext := path.Ext(imagePath)
				base := imagePath[:len(imagePath)-len(ext)]
				newImagePath := fmt.Sprintf("%s_old_%d%s", base, currentTime, ext)

				// Rename the file
				oldFilePath := path.Join("public", imagePath) // Assuming imagePath is relative to public
				newFilePath := path.Join("public", newImagePath)
				// Ensure the public directory is correctly referenced
				// In Go, relative paths might be tricky. Let's assume the executable is run from the project root.
				// A more robust solution would use absolute paths or a config for the public dir.
				// For now, assuming relative path from executable location.
				err := os.Rename(oldFilePath, newFilePath)
				if err != nil {
					log.Printf("Error renaming image file %s to %s: %v", oldFilePath, newFilePath, err)
					// Continue with other files/database update
				}
			}
		}
		if err := rows.Err(); err != nil {
			log.Printf("Error iterating image paths: %v", err)
		}
	}

	sqlQuery := fmt.Sprintf("UPDATE text SET %s = NULL WHERE id IN (%s)", body.Type, placeholders)

	result, err := db.Exec(sqlQuery, args...)
	if err != nil {
		log.Printf("Error deleting detail: %v", err)
		writeJSONResponse(w, 1, "删除失败", nil)
		return
	}

	rowsAffected, err := result.RowsAffected()
	if err != nil {
		log.Printf("Error getting rows affected after deleting detail: %v", err)
		writeJSONResponse(w, 1, "删除失败", nil)
		return
	}

	log.Printf("Deleted %d rows for type %s with ids %v", rowsAffected, body.Type, body.Ids)
	writeJSONResponse(w, 0, "删除成功", nil)
}

// fetch(`/role/delete/${roleId} 实现删除功能
func DeleteRole(w http.ResponseWriter, r *http.Request) {
	var body struct {
		ID string `json:"id"`
	}
	if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
		writeJSONResponse(w, 1, "请求参数错误", nil)
		return
	}
	if body.ID == "" {
		writeJSONResponse(w, 1, "id不能为空", nil)
		return
	}
	// 从数据库删除
	_, err := db.Exec("DELETE FROM role WHERE id = ?", body.ID)
	if err != nil {
		log.Printf("Error deleting role: %v", err)
		writeJSONResponse(w, 1, "删除失败", nil)
		return
	}
	writeJSONResponse(w, 0, "删除成功", nil)
}

// NewRole 处理 POST /role/new 请求
func NewRole(w http.ResponseWriter, r *http.Request) {
	var body struct {
		ID      string `json:"id"`
		Name    string `json:"name"`
		Prompt  string `json:"prompt"`
		Type    string `json:"type"`
		Remark  string `json:"remark"`
		Sound   string `json:"sound"`
		ImgPath string `json:"imgPath"`
	}

	if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
		writeJSONResponse(w, 1, "请求参数错误", nil)
		return
	}

	if body.Name == "" || body.Prompt == "" {
		writeJSONResponse(w, 1, "角色名称和提示词不能为空", nil)
		return
	}
	// base64 编码
	if body.ImgPath != "" {
		// 检查base64字符串是否以data:image/png;base64,开头
		if strings.HasPrefix(body.ImgPath, "data:image/png;base64,") || strings.HasPrefix(body.ImgPath, "data:image/jpeg;base64,") {

			// base64图片保存本地
			base64Str := strings.TrimPrefix(body.ImgPath, "data:image/png;base64,")
			if strings.HasPrefix(body.ImgPath, "data:image/jpeg;base64,") {
				base64Str = strings.TrimPrefix(body.ImgPath, "data:image/jpeg;base64,")
			}
			imgData, err := base64.StdEncoding.DecodeString(base64Str)
			if err != nil {
				log.Printf("Error decoding base64 image: %v", err)
				writeJSONResponse(w, 1, "图片解码失败", nil)
				return
			}

			// 图片提交服务器
			uploadURL := "http://" + config.LoadedConfig.ComfyUI.ServerAddress + "/api/upload/image"

			// Create a buffer to store our request body
			bodyBuf := &bytes.Buffer{}
			bodyWriter := multipart.NewWriter(bodyBuf)

			// Add type field
			err = bodyWriter.WriteField("type", "input")
			if err != nil {
				log.Printf("Error writing 'type' field: %v", err)
				writeJSONResponse(w, 1, "创建上传请求失败", nil)
				return
			}

			// Add image file
			// The filename can be anything, as the server will likely generate its own.
			fileName := fmt.Sprintf("%s-%s.png", body.ID, body.Name)
			part, err := bodyWriter.CreateFormFile("image", fileName)
			if err != nil {
				log.Printf("Error creating form file: %v", err)
				writeJSONResponse(w, 1, "创建上传请求失败", nil)
				return
			}
			_, err = io.Copy(part, bytes.NewReader(imgData))
			if err != nil {
				log.Printf("Error copying image data: %v", err)
				writeJSONResponse(w, 1, "创建上传请求失败", nil)
				return
			}

			// Close the multipart writer
			bodyWriter.Close()

			// Create and send the request
			req, err := http.NewRequest("POST", uploadURL, bodyBuf)
			if err != nil {
				log.Printf("Error creating upload request: %v", err)
				writeJSONResponse(w, 1, "上传图片失败", nil)
				return
			}
			req.Header.Set("Content-Type", bodyWriter.FormDataContentType())

			client := &http.Client{}
			resp, err := client.Do(req)
			if err != nil {
				log.Printf("Error sending upload request: %v", err)
				writeJSONResponse(w, 1, "上传图片失败", nil)
				return
			}
			defer resp.Body.Close()

			if resp.StatusCode != http.StatusOK {
				bodyBytes, _ := io.ReadAll(resp.Body)
				log.Printf("Upload failed with status: %s, body: %s", resp.Status, string(bodyBytes))
				writeJSONResponse(w, 1, fmt.Sprintf("上传图片失败: %s", resp.Status), nil)
				return
			}

			// Decode the response
			var uploadResponse struct {
				Name      string `json:"name"`
				Subfolder string `json:"subfolder"`
				Type      string `json:"type"`
			}
			if err := json.NewDecoder(resp.Body).Decode(&uploadResponse); err != nil {
				log.Printf("Error decoding upload response: %v", err)
				writeJSONResponse(w, 1, "解析上传响应失败", nil)
				return
			}

			// Construct the image path for the database
			// Assuming the server returns the filename and we can construct the path
			body.ImgPath = path.Join(uploadResponse.Subfolder, uploadResponse.Name)

			// 图片存储项目\public\html\personImgs\角色ID.png
			imgPath := fmt.Sprintf("public/html/personImgs/%s", body.ImgPath)
			err = os.MkdirAll(filepath.Dir(imgPath), 0755)
			if err != nil {
				log.Printf("Error creating directory: %v", err)
				writeJSONResponse(w, 1, "创建目录失败", nil)
				return
			}
			err = os.WriteFile(imgPath, imgData, 0644)
			if err != nil {
				log.Printf("Error writing image file: %v", err)
				writeJSONResponse(w, 1, "保存图片失败", nil)
				return
			}

		}
	}

	// 检查角色ID是否已存在，如果存在则更新，否则插入
	if body.ID != "" {
		// 检查ID是否存在
		var exists int
		err := db.DB.QueryRow("SELECT COUNT(*) FROM role WHERE id = ?", body.ID).Scan(&exists)
		if err != nil {
			log.Printf("Error checking role existence: %v", err)
			writeJSONResponse(w, 1, "查询角色失败", nil)
			return
		}

		if exists > 0 {
			// 更新现有角色
			sqlQuery := "UPDATE role SET name = ?, prompt = ?, type = ?, remark = ?, sound = ?, imgPath = ? WHERE id = ?"
			_, err = db.Exec(sqlQuery, body.Name, body.Prompt, body.Type, body.Remark, body.Sound, body.ImgPath, body.ID)
			if err != nil {
				log.Printf("Error updating role: %v", err)
				writeJSONResponse(w, 1, "更新角色失败", nil)
				return
			}
			writeJSONResponse(w, 0, "角色更新成功", nil)
			return
		}
	}

	// 插入新角色
	sqlQuery := "INSERT INTO role (name, prompt, type, remark, sound, imgPath) VALUES (?, ?, ?, ?, ?, ?)"
	result, err := db.Exec(sqlQuery, body.Name, body.Prompt, body.Type, body.Remark, body.Sound, body.ImgPath)
	if err != nil {
		log.Printf("Error inserting new role: %v", err)
		writeJSONResponse(w, 1, "创建角色失败", nil)
		return
	}

	lastID, err := result.LastInsertId()
	if err != nil {
		log.Printf("Error getting last insert ID for role: %v", err)
		writeJSONResponse(w, 1, "创建角色失败", nil)
		return
	}

	writeJSONResponse(w, 0, "角色创建成功", map[string]interface{}{"role_id": lastID})
}

// 查询项目角色
func QueryProjectRoles(w http.ResponseWriter, r *http.Request) {
	projectIDStr := r.URL.Query().Get("project_id")
	if projectIDStr == "" {
		writeJSONResponse(w, -1, "项目ID不能为空", nil)
		return
	}
	projectID, err := strconv.Atoi(projectIDStr)
	if err != nil {
		writeJSONResponse(w, -1, "项目ID格式错误", nil)
		return
	}

	sqlQuery := "SELECT id, name, CONCAT('/public/html/personImgs/',imgPath)imgPath FROM role WHERE FIND_IN_SET(id,(SELECT role_ids from project where id =?))"

	rows, err := db.Query(sqlQuery, projectID)
	if err != nil {
		log.Printf("Error querying project details: %v", err)
		writeJSONResponse(w, -1, "查询项目角色失败", nil)
		return
	}
	defer rows.Close()

	var details []map[string]interface{}
	for rows.Next() {
		var id int
		var name sql.NullString
		var imgPath sql.NullString
		err := rows.Scan(&id, &name, &imgPath)
		if err != nil {
			log.Printf("Error scanning project detail row: %v", err)
			continue
		}

		detail := map[string]interface{}{
			"id":      id,
			"name":    name.String,
			"imgPath": imgPath.String,
		}

		details = append(details, detail)
	}

	if err = rows.Err(); err != nil {
		log.Printf("Error iterating project detail rows: %v", err)
		writeJSONResponse(w, -1, "查询项目详情失败", nil)
		return
	}

	writeJSONResponse(w, 1, "查询成功", details)
}

// QueryRole 处理 GET /role/query 请求
func QueryRole(w http.ResponseWriter, r *http.Request) {
	roleIDStr := r.URL.Query().Get("id")
	if roleIDStr == "" {
		writeJSONResponse(w, -1, "角色ID不能为空", nil)
		return
	}
	roleID, err := strconv.Atoi(roleIDStr)
	if err != nil {
		writeJSONResponse(w, -1, "角色ID格式错误", nil)
		return
	}
	// 修改QueryRole函数中role结构体的Sound字段类型
	var role struct {
		ID      int            `json:"id"`
		Name    string         `json:"name"`
		Prompt  string         `json:"prompt"`
		Type    string         `json:"type"`
		Remark  string         `json:"remark"`
		Sound   sql.NullString `json:"sound"`
		ImgPath sql.NullString `json:"imgPath"`
	}

	// 查询角色
	sqlQuery := "SELECT id, name, prompt, type, remark, sound, CONCAT('/public/html/personImgs/',imgPath)imgPath FROM role WHERE id = ?"
	err = db.QueryRow(sqlQuery, roleID).Scan(&role.ID, &role.Name, &role.Prompt, &role.Type, &role.Remark, &role.Sound, &role.ImgPath)
	if err != nil {
		log.Printf("Error querying role details: %v", err)
		writeJSONResponse(w, -1, "查询角色失败", nil)
		return
	}

	// 将sql.NullString转换为string
	responseRole := map[string]interface{}{
		"id":      role.ID,
		"name":    role.Name,
		"prompt":  role.Prompt,
		"type":    role.Type,
		"remark":  role.Remark,
		"sound":   "",
		"imgPath": "",
	}
	if role.Sound.Valid {
		responseRole["sound"] = role.Sound.String
	}
	if role.ImgPath.Valid {
		responseRole["imgPath"] = role.ImgPath.String
	}

	writeJSONResponse(w, 0, "查询成功", responseRole)
}

// QueryRole 处理 GET /role/queryAll 请求
func QueryRoles(w http.ResponseWriter, r *http.Request) {
	projectIDStr := r.URL.Query().Get("project_id")

	// 查询角色
	sqlQuery := "SELECT id, name, prompt, type, remark, sound, CONCAT('/public/html/personImgs/',imgPath)imgPath, (FIND_IN_SET(id,(select role_ids from project where id=?)))selected FROM role "
	rows, err := db.Query(sqlQuery, projectIDStr)
	if err != nil {
		log.Printf("Error querying project details: %v", err)
		writeJSONResponse(w, -1, "查询角色失败", nil)
		return
	}
	defer rows.Close()

	var details []map[string]interface{}
	for rows.Next() {
		var id int
		var name sql.NullString
		var prompt sql.NullString
		var roleType sql.NullString
		var remark sql.NullString
		var sound sql.NullString
		var imgPath sql.NullString
		var selected sql.NullString
		err := rows.Scan(&id, &name, &prompt, &roleType, &remark, &sound, &imgPath, &selected)
		if err != nil {
			log.Printf("Error scanning project detail row: %v", err)
			continue
		}

		detail := map[string]interface{}{
			"id":       id,
			"name":     name.String,
			"prompt":   prompt.String,
			"type":     roleType.String,
			"remark":   remark.String,
			"sound":    sound.String,
			"imgPath":  imgPath.String,
			"selected": selected.String,
		}

		details = append(details, detail)
	}

	if err = rows.Err(); err != nil {
		log.Printf("Error iterating project detail rows: %v", err)
		writeJSONResponse(w, -1, "查询角色失败", nil)
		return
	}

	writeJSONResponse(w, 0, "查询成功", details)
}

// 处理 GET /speaker/queryAll 请求
func QuerySpeakers(w http.ResponseWriter, r *http.Request) {
	projectIDStr := r.URL.Query().Get("project_id")

	// 查询讲述人
	sqlQuery := "SELECT id, name, type, remark, sound, (FIND_IN_SET(id,(select speaker_id from project where id=?)))selected FROM speaker "
	rows, err := db.Query(sqlQuery, projectIDStr)
	if err != nil {
		log.Printf("Error querying project details: %v", err)
		writeJSONResponse(w, -1, "查询讲述人失败", nil)
		return
	}
	defer rows.Close()

	var details []map[string]interface{}
	for rows.Next() {
		var id int
		var name sql.NullString
		var speakerType sql.NullString
		var remark sql.NullString
		var sound sql.NullString
		var selected sql.NullString
		err := rows.Scan(&id, &name, &speakerType, &remark, &sound, &selected)
		if err != nil {
			log.Printf("Error scanning project detail row: %v", err)
			continue
		}

		detail := map[string]interface{}{
			"id":       id,
			"name":     name.String,
			"type":     speakerType.String,
			"remark":   remark.String,
			"sound":    sound.String,
			"selected": selected.String,
		}

		details = append(details, detail)
	}

	if err = rows.Err(); err != nil {
		log.Printf("Error iterating project detail rows: %v", err)
		writeJSONResponse(w, -1, "查询讲述人失败", nil)
		return
	}

	writeJSONResponse(w, 0, "查询成功", details)
}
